//
//  YMWebBaseVC.m
//  GuoAo
//
//  Created by y s on 2023/3/10.
//

#import "YMWebBaseVC.h"
#import "YMScriptMessageHandler.h"

@interface YMWebBaseVC ()<WKNavigationDelegate,WKScriptMessageHandler,WKUIDelegate>

@property (nonatomic, strong) WKWebView *webView;
//进度条
@property (nonatomic, strong) UIProgressView *progressView;
//这个类主要用来做native与JavaScript的交互管理
@property (nonatomic, strong) WKUserContentController *userController;

@end

@implementation YMWebBaseVC

- (void)viewDidLoad {
    [super viewDidLoad];
    [self setUI];
    [self loadData];
    self.navBarHidden = _hideNav;
    [self addNotify];
}

#pragma mark -- UI
- (void)setUI{
    [self showNavTitle:self.strTitle];
    [self.view addSubview:self.webView];
    [self.view addSubview:self.progressView];
    [self.webView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.right.bottom.mas_equalTo(0);
        if (self.hideNav){
            make.top.mas_equalTo(20);
        }else{
            make.top.mas_equalTo(0);
        }
    }];
}
- (void)loadData{
    if (_webUrl != nil && _webUrl.length > 0){
        NSURLRequest *request = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:[SDataUtil stringOf:_webUrl valid:@""]]];
        [self.webView loadRequest:request];
    }
}

- (void)addNotify{
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reloadData) name:@"reachabilityChanged" object:nil];
//    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reloadData) name:UIApplicationDidBecomeActiveNotification object:nil];
}

- (void)reloadData{
    if (self.webView.URL != nil){
        [self.webView reload];
    }else{
        [self loadData];
    }
}

#pragma mark -- private methods
//kvo 监听进度 必须实现此方法
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
    
    if ([keyPath isEqualToString:NSStringFromSelector(@selector(estimatedProgress))] &&
        object == self.webView) {
        self.progressView.progress = self.webView.estimatedProgress;
        if (self.webView.estimatedProgress >= 1.0f) {
            WEAK_SELF;
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                weakSelf.progressView.progress = 0;
            });
        }
    }else{
        [super observeValueForKeyPath:keyPath
                             ofObject:object
                               change:change
                              context:context];
    }
}


//接收js 方法
- (void)receiveScriptMessage:(WKScriptMessage *)message{
    //获取H5页面返回的数据并转成NSDictionary类型
    if ([message.name isEqualToString:@"onFinishPage"])
    {//关闭界面
        [SJumpUtil popVC:self animated:YES];
    }
}

#pragma mark - WKScriptMessageHandler
/**
 被自定义的WKScriptMessageHandler在回调方法里通过代理回调回来
 通过接收JS传出消息的name进行捕捉的回调方法 */
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
    NSLog(@"name:%@, \n body:%@, \n info:%@", message.name, message.body, message.frameInfo);
    if (!message.name ||
        ![message.name isKindOfClass:[NSString class]] ||
        [message.name length] == 0) {
        return;
    }
    [self receiveScriptMessage:message];
}


#pragma mark -- WKNavigationDelegate
- (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler {
    if (webView != _webView) {
        return;
    }
    //适应HTTPs请求的代理方法
    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
        completionHandler(NSURLSessionAuthChallengeUseCredential,nil);
    }
}
/*
 *  WKNavigationDelegate主要处理一些跳转、加载处理操作，
 *  WKUIDelegate主要处理JS脚本，确认框，警告框等
 */
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation {
    //页面开始加载时调用
}
- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation {
    //当内容开始返回时调用
}
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
    // 页面加载完成之后调用
    [_progressView setProgress:0.0f animated:NO];
    
}
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error {
    // 页面加载失败时调用
    [_progressView setProgress:0.0f animated:NO];
}
- (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error {
    // 提交发生错误时调用
    [_progressView setProgress:0.0f animated:NO];
}
- (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation {
    // 接收到服务器跳转请求即服务重定向时之后调用
}
- (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView{
    // 进程被终止时调用
}

/**
 *  在发送请求之前，决定是否跳转
 *  可以拦截到每次加载
 */
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{
    
    NSString *absoluteStr= navigationAction.request.URL.absoluteString;
    // 调起电话
    if([absoluteStr hasPrefix:@"tel:"]){
        NSArray *params = [absoluteStr componentsSeparatedByString:@":"];
        if(params.count>1){
            NSString *phone = params[1];
            [YMBridging callPhone:phone];
        }
        decisionHandler(WKNavigationActionPolicyCancel);
        return;
    }
    decisionHandler(WKNavigationActionPolicyAllow);
}
// 警告
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler
{
   completionHandler();
}

//确认框
- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler
{

   completionHandler(1);
}

/**  输入框 */
- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * __nullable result))completionHandler
{
   completionHandler(@"");
}

- (NSDictionary *)dictOfJson:(NSString *)jsonStr{
    NSData *jsonData = [jsonStr dataUsingEncoding:NSUTF8StringEncoding];
    NSError *error;
    NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&error];
    if(error){
        return nil;
    }
    return dic;
}


#pragma mark -- setter and getter
- (WKWebView *)webView{
    if (_webView == nil){
        WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
        //这个类主要用来做native与JavaScript的交互管理
        config.userContentController = self.userController;
        
        //设置对象
        WKPreferences *preference = [[WKPreferences alloc] init];
        //最小字体大小 当将javaScriptEnabled属性设置为NO时，可以看到明显的效果
        preference.minimumFontSize = [SFitUtil fit:9];
        //设置是否支持javaScript 默认是支持的
        preference.javaScriptEnabled = YES;
        // 在iOS上默认为NO，表示是否允许不经过用户交互由javaScript自动打开窗口
        preference.javaScriptCanOpenWindowsAutomatically = YES;
        config.preferences = preference;
        config.mediaTypesRequiringUserActionForPlayback = WKAudiovisualMediaTypeNone;
        config.allowsInlineMediaPlayback = YES;
        
        _webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:config];
        _webView.navigationDelegate = self;
        _webView.UIDelegate = self;
        // 是否允许手势左滑返回上一级, 类似导航控制的左滑返回
        _webView.allowsBackForwardNavigationGestures = NO;
//        _webView.backgroundColor = STheme.D9;
//        _webView.scrollView.backgroundColor = STheme.D9;
        [_webView setOpaque:NO];
        _webView.scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
//        JSContext *context = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
//        JSValue *action = context[@"getImg"];
        //添加监测网页加载进度的观察者
        [_webView addObserver:self
                   forKeyPath:NSStringFromSelector(@selector(estimatedProgress))
                      options:0
                      context:nil];
    }
    return _webView;
}
- (WKUserContentController *)userController{
    if (_userController == nil){
        _userController = [[WKUserContentController alloc] init];
    
        //注册js 方法
        //自定义的WKScriptMessageHandler 是为了解决内存不释放的问题
        YMScriptMessageHandler *scriptHandler = [[YMScriptMessageHandler alloc] initWithDelegate:self];
        //关闭界面
        [_userController addScriptMessageHandler:scriptHandler name:@"onFinishPage"];
        
    }
    return _userController;
}
- (UIProgressView *)progressView{
    if (_progressView == nil){
        _progressView = [[UIProgressView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, [SFitUtil fit:2])];
        _progressView.tintColor = STheme.D13;
        _progressView.trackTintColor = [UIColor clearColor];
    }
    return _progressView;
}
- (void)dealloc {
    //移除ScriptMessageHandler
    [[self.webView configuration].userContentController removeScriptMessageHandlerForName:@"onFinishPage"];
    
    //移除观察者
    [self.webView removeObserver:self forKeyPath:NSStringFromSelector(@selector(estimatedProgress))];
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}



@end
